package com.shelpe.services.sinbad.service.rpt;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import com.shelpe.services.sinbad.controller.EffectMetricDto;
import com.shelpe.services.sinbad.controller.dto.AdgroupItem;
import com.shelpe.services.sinbad.controller.dto.EffectDto;
import com.shelpe.services.sinbad.controller.dto.KeywordRealtimeRank;
import com.shelpe.services.sinbad.dto.KeywordDto;
import com.shelpe.services.sinbad.entity.jpa.Adgroup;
import com.shelpe.services.sinbad.entity.jpa.Campaign;
import com.shelpe.services.sinbad.entity.jpa.DriveType;
import com.shelpe.services.sinbad.model.Keyword;
import com.shelpe.services.sinbad.model.KeywordExample;
import com.shelpe.services.sinbad.model.RptKeyword;
import com.shelpe.services.sinbad.model.RptKeywordParam;
import com.shelpe.services.sinbad.readdao.KeywordMapper;
import com.shelpe.services.sinbad.repository.jpa.AdgroupRepository;
import com.shelpe.services.sinbad.repository.jpa.CampaignRepository;
import com.shelpe.services.sinbad.service.RankingService;
import com.shelpe.services.sinbad.service.RptKeywordService;
import com.shelpe.services.sinbad.service.rtr.RealRankingService;
import com.shelpe.services.sinbad.service.simbaproxy.SimbaProxyBaseDto;

@Service
public class AdgroupService {
	@Autowired
	private RptKeywordService rptKeywordService;
	@Autowired
	private AdgroupRepository adgroupRepository;
	@Autowired
	private CampaignRepository campaignRepository;
	@Autowired
	private RankingService rankingService;
	@Autowired
	private KeywordMapper keywordMapper;
	@Autowired
	private RealRankingService realRankingService;

	public AdgroupItem updateAdgroups(List<Adgroup> pos, AdgroupItem dto) {
		AdgroupItem retDto = new AdgroupItem();
		if (pos != null && pos.size() > 0) {
			for (Adgroup po : pos) {
				if (!dto.getDriveType().equals(po.getDriveType().name())) {
					po.setDriveType(DriveType.from(dto.getDriveType()));
				}
			}
			this.adgroupRepository.save(pos);
		} else {
			retDto.setError(new SimbaProxyBaseDto.Error());
			retDto.getError().setSubMessage("该推广组不存在");
			retDto.getError().setCode(500);
			retDto.getError().setSubCode("");
			retDto.getError().setSubMessage("该推广组不存在");
			retDto.form(retDto.getError());
		}
		return retDto;
	}

	public EffectDto adgroupMetric(long adgroupID, String device, String startDate, String endDate) {
		Adgroup adgroup = this.adgroupRepository.findOne(adgroupID);
		Assert.notNull(adgroup, "该宝贝不存在");
		RptKeywordParam param = RptKeywordParam.init();
		param.setUserId(adgroup.getUserID());
		param.setAdgroupId(adgroupID);
		if (device != null) {
			param.setupDevice(device);
		}
		param.setupDate(startDate, endDate);
		RptKeyword rpt = rptKeywordService.getSummariesMetric(param);
		EffectDto dto = new EffectDto();
		if (rpt != null) {
			dto.from(rpt);
		}
		return dto;
	}

	public List<EffectDto> adgroupTrend(long adgroupID, String device, String startDate, String endDate) {
		Adgroup adgroup = this.adgroupRepository.findOne(adgroupID);
		Assert.notNull(adgroup, "该宝贝不存在");
		RptKeywordParam param = RptKeywordParam.init();
		param.setUserId(adgroup.getUserID());
		param.setAdgroupId(adgroupID);
		if (device != null) {
			param.setupDevice(device);
		}
		param.setupDate(startDate, endDate);
		List<RptKeyword> rpts = rptKeywordService.getReportsTrendByDate(param);

		List<EffectDto> dtos = new ArrayList<EffectDto>();
		if (rpts != null) {
			for (RptKeyword rpt : rpts) {
				EffectDto dto = new EffectDto();
				dto.from(rpt);
				dtos.add(dto);
			}
		}
		return dtos;
	}

	public List<EffectMetricDto> adgroupTrendByUserID(long userID, List<Long> adgroupIDs, String device, int days) {
		RptKeywordParam param = RptKeywordParam.init();
		param.setUserId(userID);
		param.setAdgroupIds(adgroupIDs);
		if (device != null) {
			param.setupDevice(device);
		}
		param.setupDays(days);
		List<RptKeyword> rpts = rptKeywordService.getReportsTrend(param);

		List<EffectMetricDto> dtos = new ArrayList<EffectMetricDto>();
		if (rpts != null) {
			for (RptKeyword rpt : rpts) {
				EffectMetricDto dto = new EffectMetricDto();
				dto.filterNull(rpt);
				dto.from(rpt);
				dtos.add(dto);
			}
		}
		return dtos;
	}

	public List<Adgroup> findAdgroup(long userID, long campaignID, long adgroupID) {
		List<Adgroup> pos = this.adgroupRepository.findAll(new Specification<Adgroup>() {
			@Override
			public Predicate toPredicate(Root<Adgroup> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				Predicate p = cb.equal(root.get("userID"), userID);
				if (campaignID > 0) {
					p = cb.and(p, cb.equal(root.get("campaignID"), campaignID));
				}
				if (adgroupID > 0) {
					p = cb.and(p, cb.equal(root.get("autoID"), adgroupID));
				}
				return p;
			}
		});
		return pos;
	}

	public EffectMetricDto report(long adgroupID, String device, int days, String startDate, String endDate) {
		RptKeywordParam param = RptKeywordParam.init();
		param.setUserId(adgroupRepository.findOne(adgroupID).getUserID());
		param.setAdgroupId(adgroupID);
		if (device != null) {
			param.setupDevice(device);
		}
		if (days > 0) {
			param.setupDays(days);
		}
		if (startDate != null) {
			param.setupDate(startDate, endDate);
		}
		if (days == 0 && StringUtils.isBlank(startDate)) {
			days = 7;
			param.setupDays(days);
		}
		RptKeyword rpt = rptKeywordService.getSummariesMetric(param);
		EffectMetricDto dto = new EffectMetricDto();
		if (rpt != null) {
			dto.filterNull(rpt);
			dto.from(rpt);
		}
		return dto;
	}

	// 获取可养分的关键词个数
	public int sumMobileKeywords(long adgroupID) {
		Adgroup adgroup = adgroupRepository.findOne(adgroupID);
		if (adgroup == null) {
			return 0;
		}
		List<KeywordDto> dtos = new ArrayList<KeywordDto>();
		// 获取关键词元数据
		KeywordExample ex = new KeywordExample();
		ex.setUserId(adgroup.getUserID());
		KeywordExample.Criteria criteria = ex.createCriteria();
		criteria.andAdgroupIdEqualTo(adgroup.getAutoID());
		List<Keyword> keywords = this.keywordMapper.selectByExample(ex);
		if (keywords == null || keywords.size() == 0) {
			return 0;
		}

		Map<Long, KeywordDto> dtoMap = new HashMap<Long, KeywordDto>();
		for (Keyword kw : keywords) {
			KeywordDto dto = new KeywordDto();
			dto.from(kw, 0);
			dtoMap.put(kw.getKeywordId(), dto);
		}

		RptKeywordParam param = new RptKeywordParam();
		param.setUserId(adgroup.getUserID());
		param.setAdgroupId(adgroup.getAutoID());
		param.setupDays(7);
		param.setupDevice("mobile");

		List<RptKeyword> rpts = rptKeywordService.getReportsTrend(param);
		EffectMetricDto adgroupEffectMetirc = this.report(adgroupID, "mobile", 7, null, null);
		for (RptKeyword rpt : rpts) {
			if (dtoMap.get(rpt.getKeywordId()) != null) {
				if (dtoMap.get(rpt.getKeywordId()).getMobileQscore() > 5
						&& dtoMap.get(rpt.getKeywordId()).getMobileQscore() < 10 && rpt.getClick() > 10) {
					if (rpt.getRoi() > 0 || (rpt.getRoi() == 0 && (adgroupEffectMetirc.getFavTotal()
							+ adgroupEffectMetirc.getCartTotal()) > adgroupEffectMetirc.getCtr() * 0.05)) {
						KeywordDto dto = dtoMap.get(rpt.getKeywordId());
						if (dto != null) {
							dto.from(rpt);
						}
						dtos.add(dto);
					}
				}
			}
		}
		this.rankingService.checkKeywordRanking(adgroup.getUserID(), dtos);

		/* 排名前三的不可养分 */
		if (dtos.size() > 0) {
			dtos = this.filterMobileKeywordsByMobileRank(dtos, adgroup.getUserID());
		}
		return dtos.size();
	}

	/**
	 * @description 过滤无线排名前三的关键词
	 * 
	 * @return
	 * @author letian@shelpe.com
	 * @date 2017年10月31日 下午4:08:26
	 */
	public List<KeywordDto> filterMobileKeywordsByMobileRank(List<KeywordDto> keywordsDto, long userID) {
		List<Long> keywordIDs = new ArrayList<Long>();
		for (KeywordDto keywordDto : keywordsDto) {
			keywordIDs.add(keywordDto.getKeywordID());
		}

		/** 查询关键词 **/
		KeywordExample ke = new KeywordExample();
		ke.setUserId(userID);
		ke.createCriteria().andKeywordIdIn(keywordIDs);
		List<Keyword> keywords = this.keywordMapper.selectByExample(ke);

		// 15分钟内的排名
		int time = 15;
		Date queryTime = DateUtils.addMinutes(new Date(), -time);
		List<KeywordRealtimeRank> dtos = new ArrayList<KeywordRealtimeRank>();
		Map<Long, KeywordRealtimeRank> mapKeywordRank = new HashMap<Long, KeywordRealtimeRank>();
		if (keywords != null && keywords.size() > 0) {
			dtos = this.realRankingService.findRanking(keywords, keywords.get(0).getAdgroupId(), keywordIDs, queryTime,
					"mobile", time);
			if (dtos == null || dtos.size() == 0) {
				dtos = this.realRankingService.syncRanking(keywords, keywords.get(0).getAdgroupId(), keywordIDs,
						"mobile", time);
			}
		}

		for (KeywordRealtimeRank rank : dtos) {
			mapKeywordRank.put(rank.getKeywordID(), rank);
		}

		// 判断是否移动前三
		List<KeywordDto> res = new ArrayList<KeywordDto>();
		for (KeywordDto keywordDto : keywordsDto) {
			if (mapKeywordRank.get(keywordDto.getKeywordID()) != null
					&& mapKeywordRank.get(keywordDto.getKeywordID()).getWirelessRank() > 1) {
				res.add(keywordDto);
			}
		}
		return res;
	}

	/**
	 * @description 新的需求,判断哪些宝贝适合无线养分
	 * 
	 * @return
	 * @author letian@shelpe.com
	 * @date 2017年8月19日 下午5:39:39
	 */
	public Map<Long, RptKeyword> mobileAdgroupIDs(long campaignID) {
		Map<Long, RptKeyword> adgroupIDs = new HashMap<Long, RptKeyword>();
		if (campaignID > 0) {
			Campaign campaign = campaignRepository.findOne(campaignID);
			int budget = campaign.getBudget();
			if (budget >= 100) {
				RptKeywordParam param = RptKeywordParam.init();
				param.setUserId(campaign.getUserID());
				param.setCampaignId(campaignID);
				param.setupDevice("mobile");
				param.setupDays(7);
				List<RptKeyword> rpts = rptKeywordService.getReportsTrend(param);
				if (rpts != null) {
					for (RptKeyword rpt : rpts) {
						if (rpt.getClick() >= 50 && rpt.getRoi() > 0 && sumMobileKeywords(rpt.getAdgroupId()) > 0) {
							adgroupIDs.put(rpt.getAdgroupId(), rpt);
						}
						if (rpt.getClick() >= 50 && rpt.getRoi() == 0
								&& (rpt.getFavCount() + rpt.getCartTotal()) / 7 > (rpt.getClick() / 7) * 0.05
								&& sumMobileKeywords(rpt.getAdgroupId()) > 0) {
							adgroupIDs.put(rpt.getAdgroupId(), rpt);
						}
					}
				}
			}
		}
		return adgroupIDs;
	}
}
